package com.dabbo.starship.app.text.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.dabbo.starship.container.ContainerShip;
import com.dabbo.starship.interfaces.Block;
import com.dabbo.starship.interfaces.Cell;
import com.dabbo.starship.interfaces.CellLocationInterface;
import com.dabbo.starship.interfaces.ConsoleMode;
import com.dabbo.starship.interfaces.Container;
import com.dabbo.starship.interfaces.PlayerPoolInterface;
import com.dabbo.starship.interfaces.UniverseInterface;
import com.dabbo.starship.player.PlayerUnit;
import com.dabbo.starship.shared.CellLocation;

public class TestGameClient {

	private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	private Registry registry = null;
	private Container cp = null;
	private UniverseInterface universe = null;
	private PlayerPoolInterface playerPool = null;
	private PlayerUnit pl;
	
	public TestGameClient() {
	}

	public void startGame() throws RemoteException {

		//pl = new PlayerUnit();
		
		boolean runClient = true;
		try {
			registry = LocateRegistry.getRegistry("localhost", 3232);
			universe = (UniverseInterface) (registry.lookup("universe"));
			cp = new ContainerShip("USS Dabbo");
			cp.setPlayerID("DABBO07");
			
			//universe.initPlayerShip(cp);
			
			//playerPool = (PlayerPoolInterface)(registry.lookup("pool"));
		} catch (Exception ex) {
			System.out.println("Ouch!");
			System.out.println(ex);
			System.exit(1);
		}

		pl.setActiveStatus(true);
		pl.setCommandCode("");
		pl.setContainerID(cp.hashCode());
		pl.setCredits(10000);
		pl.setHealth(100);
		pl.setLocation(new CellLocation(4,4));
		pl.setPlayerName("Dabbo");
		pl.setRoomID(cp.getEntryBlock());
		
		Block blk;
		Cell cl;
		
		while(runClient) {
			
			blk = cp.getBlock(pl.getRoomID());
			
			System.out.println("R:" + blk.getDescription() + " [y" + pl.getCoY() + "-x" + pl.getCoX()+"]");
			System.out.println("Ready>");
			String userCommand = getUserInput();
			if (userCommand.equalsIgnoreCase("quit")) {
				runClient = false;
			}
			
			if (userCommand.equalsIgnoreCase("left")) {
				if (pl.getLocation().getCoX() > 0) {
					CellLocation newPos = new CellLocation(pl.getCoY(), pl.getCoX() - 1);
					Cell newLoc = blk.getCell(newPos);
					moveAction(newPos, newLoc);
				} else {
					System.out.println("Ouch! I cant go that way.");
				}
			}
			if (userCommand.equalsIgnoreCase("right")) {
				if (pl.getLocation().getCoX() < 8) {
					CellLocation newPos = new CellLocation(pl.getCoY(), pl.getCoX() + 1);
					Cell newLoc = blk.getCell(newPos);
					moveAction(newPos, newLoc);
				} else {
					System.out.println("Ouch! I cant go that way.");
				}
			}
			if (userCommand.equalsIgnoreCase("up")) {
				if (pl.getLocation().getCoY() > 0) {
					CellLocation newPos = new CellLocation(pl.getCoY() - 1, pl.getCoX());
					Cell newLoc = blk.getCell(newPos);
					moveAction(newPos, newLoc);
				} else {
					System.out.println("Ouch! I cant go that way.");
				}
			}
			if (userCommand.equalsIgnoreCase("down")) {
				if (pl.getLocation().getCoY() < 8) {
					CellLocation newPos = new CellLocation(pl.getCoY() + 1, pl.getCoX());
					Cell newLoc = blk.getCell(newPos);
					moveAction(newPos, newLoc);
				} else {
					System.out.println("Ouch! I cant go that way.");
				}
			}
			if (userCommand.equalsIgnoreCase("look")) {
				lookAround();
			}

		}

		System.out.println("Exit OK.");
		System.exit(0);
		
	}
	
	private String getUserInput() {
		System.out.print("> ");
		String userCommand = "";
		try {
			userCommand = br.readLine();
		} catch (IOException ioe) {
			System.out.println("IO error!");
			System.exit(1);
		}
		return userCommand;
	}
	
	private void lookAround() throws RemoteException  {
		Block blk = cp.getBlock(pl.getRoomID());

		System.out.println("[" + blk.getDescription() + "] room layout:");
			
		for (int y = 0; y < 9; y++) {
			for (int x = 0; x < 9; x++) {
				String map = "";
				switch(blk.getCell(new CellLocation(y, x)).getCellType()) {
				case Cell.CELL_DEFAULT:
					map = "#";
					break;
				case Cell.CELL_DOOR:
					map = "D";
					break;
				case Cell.CELL_FLOOR:
					map = " ";
					break;
				case Cell.CELL_POWER:
					map = "P";
					break;
				case Cell.CELL_ENGINE:
					map = "E";
					break;
				case Cell.CELL_ENGINE_CORE:
					map = "e";
					break;
				case Cell.CELL_BED:
					map = "B";
					break;
				case Cell.CELL_CONSOLE:
					map = "C";
					break;
				case Cell.CELL_MEDBED:
					map = "M";
					break;
				default:
					map = "?";
				}
				if ((y == pl.getCoY()) && (x == pl.getCoX())) {
					map = "@";
				}
				System.out.print(map);
			}
			System.out.print("\n");
		}
	}

	private void moveAction(CellLocation newPos, Cell newLoc) throws RemoteException {
		switch (newLoc.getCellType()) {
		case Cell.CELL_DEFAULT:
			System.out.println("A wall is in the way!");
			break;
		case Cell.CELL_FLOOR:
			pl.setLocation(newPos);
			System.out.println("Moved.");
			break;
		case Cell.CELL_DOOR:
			pl.setRoomID(newLoc.getExitBlock().hashCode());
			CellLocationInterface dab = newLoc.getExitCell();
			pl.setLocation(dab);
			System.out.println("You have entered the room : " + cp.getBlock(pl.getRoomID()).getDescription());
			break;
		case Cell.CELL_POWER:
			String status = "OFFLINE";
			if (newLoc.isActive()) {
				status = "ONLINE";
			}
			System.out.println("Reactor Node, Status: " + status + " ~ Output : " + newLoc.getPowerOutput());
			System.out.println("Control Options:");
			System.out.println("----------------");
			System.out.println("  1. Power up Reactor Node.");
			System.out.println("  2. Shutdown Reactor Node.");
			String userCommand = getUserInput();
			if (userCommand.equals("1")) {
				newLoc.activate();
			}
			if (userCommand.equals("2")) {
				newLoc.deActivate();
			}
			System.out.println("Command executed.");
			break;
		case Cell.CELL_CONSOLE:
			openConsole(newLoc);
			break;
		default:
			System.out.println("Unknown cell : " + newLoc.getCellType());
		}
	}

	private void displayConsoleTitle(String title) {
		System.out.println("****************************");
		System.out.println("    Console System v1,02    ");
		System.out.println("****************************");
		System.out.println("Mode: " + title);
		System.out.println("****************************");
		System.out.println("Logon success.");
		System.out.println("      -= Menu Options =-");
		System.out.println("  --[Console]----------------");
		System.out.println("  1. Power down.");
		System.out.println("  2. Room Lighting toggle.");
		System.out.println("  3. Map Console Function.");
		System.out.println("  --[Functions]--------------");
	}
	
	private void commonCommandCheck(String userCommand, Cell cellConsole) throws RemoteException {
		if (userCommand.equals("1")) {
			cellConsole.deActivate();
			System.out.println("  ** Shutting down console.");
		}
		if (userCommand.equals("2")) {
			if (!cp.getBlock(pl.getRoomID()).isBlockLit()) {
				cp.getBlock(pl.getRoomID()).setLighting(true);
				System.out.println("  ** Room lights ON.");
			} else {
				cp.getBlock(pl.getRoomID()).setLighting(false);
				System.out.println("  ** Room lights OFF.");
			}
		}
		if (userCommand.equals("3")) {
			System.out.println("    Select Function:");
			System.out.println("    a. No function.");
			System.out.println("    b. Power Systems.");
			System.out.println("    c. Reastor Systems.");
			userCommand = getUserInput();
			if (userCommand.equalsIgnoreCase("a")) {
				System.out.println("      - Mode set to no function.");
				cellConsole.setConsoleMode(ConsoleMode.MODE_UNASSIGNED);
			}
			if (userCommand.equalsIgnoreCase("b")) {
				System.out.println("      - Mode set to Power Systems.");
				cellConsole.setConsoleMode(ConsoleMode.MODE_ENGINEERING);
			}
			if (userCommand.equalsIgnoreCase("c")) {
				System.out.println("      - Mode set to Reactor Systems.");
				cellConsole.setConsoleMode(ConsoleMode.MODE_ENGINEERING);
			}
		}
	}
	
	private void openConsole(Cell cellConsole) throws RemoteException {

		if (cellConsole.isActive()) {
			boolean usedConsole = false;
			if (cellConsole.getConsoleMode() == ConsoleMode.MODE_UNASSIGNED) {
				usedConsole = true;
				displayConsoleTitle("No Function Setup.");
				System.out.println("  * Terminal Mode Disabled *");
				String userCommand = getUserInput();
				commonCommandCheck(userCommand, cellConsole);
			}
			if (cellConsole.getConsoleMode() == ConsoleMode.MODE_ENGINEERING && !usedConsole) {
				usedConsole = true;
				displayConsoleTitle("Power System Cosnole.");
				System.out.println("  4. Power Report");
				System.out.println("  5. Ship-wide lighting toggle.");
				String userCommand = getUserInput();
				commonCommandCheck(userCommand, cellConsole);
				if (userCommand.equals("4")) {
					System.out.println("  ---------------------------");
					System.out.println("  Power Report");
					System.out.println("  ---------------------------");
					int engines = 0;
					int reactors = 0;
					int lighting = 0;
					int consoles = 0;
					HashMap<Integer, Block> blks = cp.getAllBlocks();
					Set<Entry<Integer, Block>> set = blks.entrySet(); 
					Iterator<Entry<Integer, Block>> i = set.iterator(); 
					while(i.hasNext()) { 
						Map.Entry<Integer, Block> ent = (Map.Entry<Integer, Block>) i.next();
						Block blk = (Block) ent.getValue();
						for (int y = 0; y < 8; y++) {
							for (int x = 0; x < 8; x++) {
								switch(blk.getCells()[y][x].getCellType()) {
								case Cell.CELL_ENGINE_CORE:
									engines = engines + blk.getCells()[y][x].getPowerOutput();
									break;
								case Cell.CELL_CONSOLE:
									consoles = consoles + blk.getCells()[y][x].getPowerOutput();
									break;
								case Cell.CELL_POWER:
									reactors = reactors + blk.getCells()[y][x].getPowerOutput();
									break;
								}
							}
						}
						if (blk.isBlockLit()) {
							lighting = lighting - 8;
						}
						System.out.println("  - Room : " + blk.getDescription() + ", power output : " + blk.getPowerOutput());
					}
					System.out.println("  -");
					System.out.println("  * Total Lighting Drain : " + lighting);
					System.out.println("  * Total Console Drain  : " + consoles);
					System.out.println("  * Total Engines Drain  : " + engines);
					System.out.println("  * Total Reactor Suply  : " + reactors);
					System.out.println("  -");
					System.out.println("  Power Balance          : " + cp.getPowerOutput());
					System.out.println("  ---------------------------");
					System.out.println("  End of report" );
				}
			}
			System.out.println("Logging off.");
			System.out.println("Power Usage: " + cellConsole.getPowerOutput());
			System.out.println("****************************");
		} else {
			System.out.println("  ** This console if offline, power up? (y)");
			String userCommand = getUserInput();
			if (userCommand.equalsIgnoreCase("y")) {
				cellConsole.activate();
				System.out.println("  ** Booting up console.");
			}
		}
		
	}
	
	public static void main(String[] args) throws RemoteException {

		TestGameClient newGame = new TestGameClient();
		newGame.startGame();
		
	}

	
}
